package com.task.service.impl;

import com.task.common.entity.sys.model.LoginBody;
import com.task.common.entity.sys.model.LoginUser;
import com.task.common.entity.sys.UserLog;
import com.task.common.exception.ServiceException;
import com.task.common.exception.user.CaptchaException;
import com.task.common.exception.user.CaptchaExpireException;
import com.task.common.exception.user.UserPasswordNotMatchException;
import com.task.common.util.constant.Constants;
import com.task.common.util.date.DateUtils;
import com.task.common.util.ip.IpUtils;
import com.task.common.util.redis.RedisCache;
import com.task.common.util.servlet.ServletUtils;
import com.task.service.IUserLogService;
import com.task.service.IUserService;
import com.task.service.LoginService;
import com.task.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author Huzz
 * @created 2021-12-01 19:16
 */
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private RedisCache redisCache;

    @Resource
    private AuthenticationManager authenticationManager;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IUserLogService userLogService;

    @Override
    public String login(LoginBody user) {
        String username = user.getUsername();
        String password = user.getPassword();
        String code = user.getCode();
        String uuid = user.getUuid();

        /** 校验验证码 */
        validateCaptcha(username, code, uuid);

        Authentication token = new UsernamePasswordAuthenticationToken(username, password);
        Authentication authentication;
        try {
            authentication = authenticationManager.authenticate(token);
        } catch (BadCredentialsException e) {
            throw new UserPasswordNotMatchException();
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }

        // 记录登录信息
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId(), loginUser.getUsername());
        // 生成Jwt token
        return tokenService.createToken(loginUser);
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     * @param username
     */
    public void recordLoginInfo(Integer userId, String username) {
        UserLog userLog = new UserLog();
        userLog.setUserId(userId);
        userLog.setUsername(username);
        userLog.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        userLog.setLoginDate(DateUtils.getNowDate());
        userLogService.updateByUserId(userLog);
    }

    /**
     * 校验验证码
     *
     * @param username 用户名
     * @param code     验证码
     * @param uuid     唯一标识
     * @return 结果
     */
    public void validateCaptcha(String username, String code, String uuid) {
        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
        String captcha = redisCache.getCacheObject(verifyKey);
        redisCache.deleteObject(verifyKey);
        if (captcha == null) {
            // TODO AsyncManager.me()
            // AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
            throw new CaptchaExpireException();
        }
        if (!code.equalsIgnoreCase(captcha)) {
            // TODO AsyncManager.me()
            // AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
            throw new CaptchaException();
        }
    }
}
